home *** CD-ROM | disk | FTP | other *** search
/ Nebula 1 / Nebula One.iso / Utilities / Workspace / LibInspector / Source / LibInspector.m < prev    next >
Text File  |  1995-06-12  |  9KB  |  311 lines

  1. //----------------------------------------------------------------------------------------------------
  2. //
  3. //    LibInspector
  4. //
  5. //    Inherits From:        WMInspector
  6. //
  7. //    Declared In:        LibInspector.h
  8. //
  9. //    Disclaimer
  10. //
  11. //        You may freely copy, distribute and reuse this software and its
  12. //        associated documentation. I disclaim any warranty of any kind, 
  13. //        expressed or implied, as to its fitness for any particular use.
  14. //
  15. //----------------------------------------------------------------------------------------------------
  16. #import "LibInspector.h"
  17.  
  18.  
  19. #define AR_TV                    "ar tv"
  20. #define AR_X                        "ar x"
  21. #define CD                        "cd"
  22. #define MKDIR                    "mkdir"
  23. #define EXTRACTION_FOLDER        "/tmp/LibExtractions"
  24. #define OUT_OF_MEMORY        "Out of Memory!"
  25. #define MKDIR_ERROR            "Unable to create temporary folder!"
  26. #define PROCESS_ERROR            "Unable to open process stream!"
  27. #define PARSE_ERROR            "Unable to recognize library information!"
  28. #define MAX_AR_FILENAME_LEN     16
  29.  
  30. static FILE*    responseStream;
  31.  
  32.  
  33. @implementation LibInspector
  34.  
  35. static id     _SELF = nil;
  36.  
  37. //----------------------------------------------------------------------------------------------------
  38. //  Private Methods
  39. //----------------------------------------------------------------------------------------------------
  40. - _alert: (STR) errorMessage
  41. {
  42.     NXRunAlertPanel (NULL, "%s", NULL, NULL, NULL, errorMessage);
  43.     return self;
  44. }
  45.  
  46.     
  47. - _getTableOfContents
  48. {
  49.     //  Get library's table of contents by sending AR_TV command.
  50.     //  Response stream will be read to populate browser (in brower:fillMatrix:inColumn).
  51.     
  52.     STR        command;
  53.     char     currentPath [MAXPATHLEN+1];
  54.     
  55.     [self selectionPathsInto:currentPath separator:'\0'];
  56.     
  57.     if (! (command = malloc (strlen (AR_TV) + strlen (currentPath) + 2)))
  58.         {
  59.         [self _alert: OUT_OF_MEMORY];
  60.         return nil;
  61.         }
  62.         
  63.     sprintf (command, "%s %s", AR_TV, currentPath);
  64.  
  65.     if (! (responseStream = popen (command, "r")))
  66.         {
  67.         if (command) free (command);
  68.         [self _alert: PROCESS_ERROR];
  69.         return nil;
  70.         }        
  71.  
  72.     if (command) free (command);
  73.     return self;
  74. }
  75.  
  76.  
  77. - (BOOL)_createLibExtractionFolder
  78. {
  79.     //  Make a temporary directory for extractions  (EXTRACTION_FOLDER).  
  80.     //  Return YES if exists/successful, NO if error.
  81.     
  82.     STR            command;
  83.     struct stat    statBuffer;
  84.     
  85.     if (stat (EXTRACTION_FOLDER, &statBuffer) == 0) return YES;
  86.  
  87.     if (! (command = malloc (strlen (MKDIR) + strlen (EXTRACTION_FOLDER) + 2)))
  88.         {
  89.         [self _alert: OUT_OF_MEMORY];
  90.         return NO;
  91.         }
  92.         
  93.     sprintf (command, "%s %s", MKDIR, EXTRACTION_FOLDER);
  94.     
  95.     system (command);
  96.     
  97.     if (stat (EXTRACTION_FOLDER, &statBuffer) != 0)
  98.         {
  99.         if (command) free (command);
  100.         [self _alert: MKDIR_ERROR];
  101.         return NO;
  102.         }
  103.  
  104.     if (command) free (command);
  105.     return YES;
  106. }
  107.     
  108.     
  109. - _openLibExtractionsFileViewer
  110. {
  111.     //  Search the application's windowList for the LibExtractions FileViewer.  
  112.     //  Open the window if it exists, open a new one if not.  This will prevent 
  113.     //  multiple FileViewers from being displayed.
  114.     
  115.     int    iterator;
  116.     int    openStatus;
  117.     id    windowList = [NXApp windowList];
  118.     id    libExtractionsFileViewer = nil;
  119.     id    appListener = NXResponsibleDelegate ([NXApp appListener], @selector(openFile:ok:));
  120.     
  121.     for (iterator = 0; iterator < [windowList count]; iterator++)
  122.         if (NXOrderStrings ([[windowList objectAt:iterator] title], "LibExtractions", 
  123.             YES, strlen ("LibExtractions"), NULL) == 0)
  124.             libExtractionsFileViewer = [windowList objectAt:iterator];
  125.             
  126.     if (libExtractionsFileViewer)
  127.         if ([libExtractionsFileViewer style] == NX_MINIWINDOWSTYLE)
  128.             [libExtractionsFileViewer deminiaturize:nil]; 
  129.         else 
  130.             [libExtractionsFileViewer makeKeyAndOrderFront:nil];
  131.     else
  132.         [appListener openFile: EXTRACTION_FOLDER ok: &openStatus];
  133.  
  134.     return self;
  135. }
  136.  
  137.  
  138. - _extractSelectedFiles
  139. {
  140.     //  Extract selected files into a temporary folder and open that folder.
  141.     
  142.     id        selectionList = [browser getSelectedCells: nil];
  143.     int        iterator;
  144.     STR        command;
  145.     STR        filename;
  146.     char     currentPath [MAXPATHLEN+1];
  147.     
  148.     if ([selectionList count])  if (! [self _createLibExtractionFolder]) return nil;
  149.  
  150.     [self selectionPathsInto: currentPath separator:'\0'];
  151.     
  152.     if (! (command = malloc (strlen (CD) + strlen (EXTRACTION_FOLDER) + 
  153.         strlen (AR_X) + MAXPATHLEN + MAX_AR_FILENAME_LEN + 10)))
  154.         {
  155.         [self _alert: OUT_OF_MEMORY];
  156.         return nil;
  157.         }
  158.         
  159.     for (iterator = 0; iterator < [selectionList count]; iterator++)
  160.         {
  161.         filename = NXCopyStringBuffer ([[selectionList objectAt: iterator] stringValue]);
  162.         if (! (filename = strtok (filename, " \t\n")))
  163.             {
  164.             if (command) free (command);
  165.             return nil;
  166.             }
  167.         sprintf (command, "%s %s; %s %s %s", CD, EXTRACTION_FOLDER, AR_X, 
  168.             currentPath, filename);
  169.         system (command);
  170.         if (filename) free (filename);
  171.         }
  172.         
  173.     [self _openLibExtractionsFileViewer];
  174.  
  175.     if (command) free (command);
  176.     return self;
  177. }
  178.  
  179.  
  180. - (STR)_format: (STR)responseLine
  181. {
  182.     //  Parse and format the response line.  Where a token gets memcpy'd within the
  183.     //  formatString indicates its position within the displayed string.  Have to exclude
  184.     //  some information. Also, throw out names beginning with '__.'.  These are archive 
  185.     //  table names, header stuff, etc., (or possibly very weird file names).  Returns a 
  186.     //  formatted string that the caller must free, or some error condition.
  187.     //  (example response line)  "rw-r--r--  0/1   4572 Jul 29 23:53 1992 NXImage.o".
  188.  
  189.     STR        currentToken;
  190.     char        formatString[51];
  191.  
  192.     memset (formatString, ' ', 50);
  193.     formatString [50] = '\0';
  194.  
  195.     if (! strtok (responseLine, " \t")) return PARSE_ERROR;
  196.     if (! strtok (NULL, "  \t")) return PARSE_ERROR;
  197.     if (! (currentToken = strtok (NULL, " \t\n"))) return PARSE_ERROR;
  198.     memcpy (formatString + 18, currentToken, strlen (currentToken));
  199.     if (! (currentToken = strtok (NULL, " \t\n"))) return PARSE_ERROR;
  200.     memcpy (formatString + 26, currentToken, strlen (currentToken));
  201.     if (! (currentToken = strtok (NULL, " \t\n"))) return PARSE_ERROR;
  202.     memcpy (formatString + 30, currentToken, strlen (currentToken));
  203.     if (! (currentToken = strtok (NULL, " \t\n"))) return PARSE_ERROR;
  204.     if (! (currentToken = strtok (NULL, " \t\n"))) return PARSE_ERROR;
  205.     memcpy (formatString + 33, currentToken, strlen (currentToken));
  206.     if (! (currentToken = strtok (NULL, " \t\n"))) return PARSE_ERROR;
  207.     memcpy (formatString, currentToken, strlen (currentToken));
  208.  
  209.     if (NXOrderStrings (currentToken, "__.", NO, 3, NULL) == 0) return NULL;
  210.     
  211.     return NXCopyStringBuffer (formatString);
  212. }
  213.  
  214.  
  215. //----------------------------------------------------------------------------------------------------
  216. //  WMInspector Methods
  217. //----------------------------------------------------------------------------------------------------
  218. + new
  219. {
  220.     //  Required/called by WM.  Only allow one instance...
  221.     
  222.         char     path[MAXPATHLEN+1];
  223.         id         bundle;
  224.  
  225.         if (_SELF) return _SELF;
  226.  
  227.         _SELF = self = [super new];
  228.  
  229.         if ( ! (bundle = [NXBundle bundleForClass:[LibInspector class]] ) ) return nil;          
  230.     if ( ! [bundle getPath:path forResource:"LibInspector" ofType:"nib"] ) return nil;
  231.         [NXApp loadNibFile:path owner:self  withNames:NO fromZone:[self zone]];
  232.  
  233.      return _SELF;
  234. }
  235.  
  236.  
  237. - revert: sender
  238. {
  239.     //  Called by WM when file selection is type we inspect.    
  240.     [self _getTableOfContents];
  241.     [[[self okButton] setTitle: "Extract"] setIconPosition: NX_TITLEONLY];
  242.     [browser loadColumnZero];
  243.     return [super revert: sender];
  244. }
  245.  
  246.  
  247. - ok:sender
  248. {
  249.     //  User pressed 'Extract' button...
  250.     
  251.     [self _extractSelectedFiles];
  252.     return [super ok:sender];
  253. }
  254.  
  255.  
  256. //----------------------------------------------------------------------------------------------------
  257. //  Action Methods
  258. //----------------------------------------------------------------------------------------------------
  259. - browserClicked: sender
  260. {
  261.     //  A file or files have been selected in the browser.  Enable 'Extract'
  262.     //  button if not an empty selection.
  263.         
  264.     if ([browser selectedCell]) 
  265.         [[self okButton] setEnabled: YES];
  266.     else
  267.         [[self okButton] setEnabled: NO];
  268.  
  269.     return self;
  270. }
  271.  
  272.  
  273. //----------------------------------------------------------------------------------------------------
  274. //  Browser Delegate Method
  275. //----------------------------------------------------------------------------------------------------
  276. - (int) browser: aBrowser fillMatrix: aMatrix inColumn: (int)aColumn
  277. {
  278.     //  Populate Table Of Contents browser with formatted command response.
  279.     //  Set the font for the browser text here (fixed font for even column alignment).
  280.     //  Minimal error checking within read loop - NULL indicates an entry we want
  281.     //  to skip (like an archive header), PARSE_ERROR indicates a response that
  282.     //  could not be recognized, all else are considered successful.
  283.     
  284.     id        font = [Font newFont: "Courier" size: 10];
  285.     int        count = 0;
  286.     char        nextLine [81];
  287.     STR        formattedLine;
  288.     
  289.     while (fgets (nextLine, 999, responseStream))
  290.         {
  291.         if ( (formattedLine = [self _format: nextLine]) == NULL) continue;
  292.         if ( NXOrderStrings (formattedLine, PARSE_ERROR, YES, -1, NULL) == 0)
  293.             {
  294.             [self _alert: PARSE_ERROR];
  295.             break;
  296.             }
  297.         [aMatrix renewRows: (count+1) cols: 1];
  298.         [[aMatrix cellAt: count :0] setFont: font];
  299.         [[aMatrix cellAt: count :0] setStringValue: formattedLine];
  300.         [[[aMatrix cellAt: count :0] setLoaded: YES] setLeaf: YES];
  301.         if (formattedLine) free (formattedLine);
  302.         count++;
  303.         }
  304.  
  305.     if (font) [font free];
  306.     pclose (responseStream);
  307.     return count;
  308. }
  309.  
  310.  
  311. @end